﻿using System.Windows.Forms;
using BasecampRestAPI;
using MoveToDoList;
using NUnit.Framework;
using TestBasecampRestAPI.Fakes;
using TestBasecampRestAPI.TestBasecampUI;

namespace TestBasecampRestAPI.TestMoveToDoList
{
	[TestFixture]
	public class TestMainFormMediator
	{
		FakeMainForm _form;
		FakeProjectToDoLists _sourceProject;
		FakeProjectToDoLists _targetProject;
		FakeCredentialsForm _credentials;
		MainFormMediator _mediator;
		FakeRestWebService _service;
		FakeBaseCamp _camp;

		[SetUp]
		public void SetUp()
		{
			_credentials = FakeCredentialsForm.GetInstance();
			_service = FakeRestWebService.GetInstance();
			_credentials.ServiceGetFakeResult = _service;
			_sourceProject = FakeProjectToDoLists.GetInstance();
			_targetProject = FakeProjectToDoLists.GetInstance();
			_form = FakeMainForm.GetInstance();
			_form.CredentialsFormGetFakeResult = _credentials;
			_form.SourceProjectGetFakeResult = _sourceProject;
			_form.TargetProjectGetFakeResult = _targetProject;
			_camp = FakeBaseCamp.GetInstance();
			_form.GetBaseCampFromCredentialsFakeCampResult = _camp;
			_form.GetBaseCampFromCredentialsFakeResult = true;
			_mediator = MainFormMediator.GetInstance(_form);
		}

		[Test]
		public void Construct()
		{
			Assert.IsNotNull(_mediator);
		}

		[Test]
		public void LoadAcceptCredentialsWithProjects()
		{
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				new FakeProject { Name = "Bar", Id = 23 }
			};
			_mediator.Load();
			Assert.IsTrue(_sourceProject.AddProjectCalled);
			Assert.IsTrue(_sourceProject.AddProjectCalledFor("Bar"));
			Assert.IsTrue(_sourceProject.AddProjectCalledFor("Foo"));
			Assert.Less(_sourceProject.AddProjectIndexFor("Bar"), _sourceProject.AddProjectIndexFor("Foo"));
			Assert.IsTrue(_sourceProject.ProjectSelectedIndexSetCalled);
			Assert.AreEqual(0, _sourceProject.ProjectSelectedIndexSetLastValue);
			Assert.IsTrue(_targetProject.AddProjectCalled);
			Assert.IsTrue(_targetProject.AddProjectCalledFor("Bar"));
			Assert.IsTrue(_targetProject.AddProjectCalledFor("Foo"));
			Assert.Less(_targetProject.AddProjectIndexFor("Bar"), _targetProject.AddProjectIndexFor("Foo"));
			Assert.IsTrue(_targetProject.ProjectSelectedIndexSetCalled);
			Assert.AreEqual(0, _targetProject.ProjectSelectedIndexSetLastValue);
		}

		[Test]
		public void SourceProjectSelectedIndexChangedNoToDoLists()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			barProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_sourceProject.ProjectSelectedIndexGetFakeResult = 0;
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			Assert.IsTrue(_sourceProject.ProjectSelectedIndexGetCalled);
			Assert.IsTrue(barProject.ToDoListsGetCalled);
			Assert.IsTrue(_sourceProject.ClearToDoListsCalled);
			Assert.IsFalse(_sourceProject.ToDoListsAddItemCalled);
		}

		[Test]
		public void SourceProjectSelectedIndexChangedWithToDoLists()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			barProject.ToDoListsGetFakeResult = new IToDoList[]
			{
				new FakeToDoList { Name = "Xenobarbs", Id = 1888 },
				new FakeToDoList { Name = "Arglefarts", Id = 1800 }
			};
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_sourceProject.ProjectSelectedIndexGetFakeResult = 0;
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			Assert.IsTrue(_sourceProject.ProjectSelectedIndexGetCalled);
			Assert.IsTrue(barProject.ToDoListsGetCalled);
			Assert.IsTrue(_sourceProject.ClearToDoListsCalled);
			Assert.IsTrue(_sourceProject.ToDoListsAddItemCalled);
			Assert.AreEqual("Xenobarbs", _sourceProject.ToDoListsAddItemLastItem);
		}

		[Test]
		public void TargetProjectSelectedIndexChangedNoToDoLists()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			barProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_targetProject.ProjectSelectedIndexGetFakeResult = 0;
			_mediator.Load();
			_mediator.TargetProjectSelectedIndexChanged();
			Assert.IsTrue(_targetProject.ProjectSelectedIndexGetCalled);
			Assert.IsTrue(barProject.ToDoListsGetCalled);
			Assert.IsTrue(_targetProject.ClearToDoListsCalled);
			Assert.IsFalse(_targetProject.ToDoListsAddItemCalled);
		}

		[Test]
		public void TargetProjectSelectedIndexChangedWithToDoLists()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			barProject.ToDoListsGetFakeResult = new IToDoList[]
			{
				new FakeToDoList { Name = "Xenobarbs", Id = 1888 },
				new FakeToDoList { Name = "Arglefarts", Id = 1800 }
			};
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_targetProject.ProjectSelectedIndexGetFakeResult = 0;
			_mediator.Load();
			_mediator.TargetProjectSelectedIndexChanged();
			Assert.IsTrue(_targetProject.ProjectSelectedIndexGetCalled);
			Assert.IsTrue(barProject.ToDoListsGetCalled);
			Assert.IsTrue(_targetProject.ClearToDoListsCalled);
			Assert.IsTrue(_targetProject.ToDoListsAddItemCalled);
			Assert.AreEqual("Xenobarbs", _targetProject.ToDoListsAddItemLastItem);
		}

		[Test]
		public void MoveButtonClick()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			FakeToDoList barList = new FakeToDoList { Name = "Xenobarbs", Id = 1888, Items = new IToDoListItem[0] };
			FakeToDoList barList2 = new FakeToDoList { Name = "Arglefarts", Id = 1800, Items = new IToDoListItem[0] };
			barProject.ToDoListsGetFakeResult = new IToDoList[] { barList, barList2 };
			FakeProject fooProject = new FakeProject { Name = "Foo", Id = 24 };
			fooProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[] { barProject, fooProject };
			_form.GetBaseCampFakeResult = _camp;
			_sourceProject.ProjectSelectedIndexGetFakeResult = 0;
			_sourceProject.SelectedListGetFakeResult = 0;
			_sourceProject.SelectedListsGetFakeResult = new[] { 0, 1 };
			_targetProject.ProjectSelectedIndexGetFakeResult = 1;
			fooProject.CreateToDoListFakeResultForName("Xenobarbs", CloneList(barList));
			fooProject.CreateToDoListFakeResultForName("Arglefarts", CloneList(barList2));
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			_mediator.TargetProjectSelectedIndexChanged();
			_mediator.MoveButtonClick();
			Assert.IsTrue(fooProject.CreateToDoListCalled);
			Assert.IsTrue(_sourceProject.SelectedListsGetCalled);
			Assert.IsTrue(_targetProject.ToDoListsAddItemCalledForName("Xenobarbs"));
			Assert.IsTrue(_targetProject.ToDoListsAddItemCalledForName("Arglefarts"));
		}

		[Test]
		public void DeleteButtonClick()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			FakeToDoList barList = new FakeToDoList { Name = "Xenobarbs", Id = 1888, Items = new IToDoListItem[0] };
			FakeToDoList barList2 = new FakeToDoList { Name = "Arglefarts", Id = 1800, Items = new IToDoListItem[0] };
			barProject.ToDoListsGetFakeResult = new IToDoList[] { barList, barList2 };
			FakeProject fooProject = new FakeProject { Name = "Foo", Id = 24 };
			fooProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[] { barProject, fooProject };
			_form.GetBaseCampFakeResult = _camp;
			_sourceProject.ProjectSelectedIndexGetFakeResult = 0;
			_sourceProject.SelectedListGetFakeResult = 0;
			_sourceProject.SelectedListsGetFakeResult = new[] { 0, 1 };
			_targetProject.ProjectSelectedIndexGetFakeResult = 1;
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			_mediator.TargetProjectSelectedIndexChanged();
			_mediator.DeleteButtonClick();
			Assert.IsTrue(barList.DeleteCalled);
			Assert.IsTrue(barList2.DeleteCalled);
		}

		private static FakeToDoList CloneList(IToDoList list)
		{
			return new FakeToDoList { Id = list.Id, Name = list.Name, Items = new IToDoListItem[0] };
		}
	}
}
